package com.weilx959.spt.plugin.e2sp.controller;

import com.jfoenix.controls.*;
import com.weilx959.spt.core.RootPaneContext;
import com.weilx959.spt.core.StageContext;
import com.weilx959.spt.core.component.VToast;
import com.weilx959.spt.core.constants.CommonConstants;
import com.weilx959.spt.core.factory.SingletonFactory;
import com.weilx959.spt.core.utils.Assert;
import com.weilx959.spt.core.utils.Try;
import com.weilx959.spt.plugin.e2sp.component.DialectListCell;
import com.weilx959.spt.plugin.e2sp.component.TableListCell;
import com.weilx959.spt.plugin.e2sp.constant.Dialect;
import com.weilx959.spt.plugin.e2sp.constant.ExcelToSqlConstants;
import com.weilx959.spt.plugin.e2sp.context.ConfigurationContext;
import com.weilx959.spt.plugin.e2sp.model.ExcelVO;
import com.weilx959.spt.plugin.e2sp.model.TransformedExcelVO;
import com.weilx959.spt.plugin.e2sp.service.ExcelToSqlService;
import com.weilx959.spt.plugin.e2sp.utils.ResourceBundleUtil;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
import javafx.scene.layout.AnchorPane;
import javafx.stage.DirectoryChooser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.util.Objects;
import java.util.Optional;
import java.util.ResourceBundle;

/**
 * 提交表单弹窗控制器
 *
 * @author weilx
 * @since 2024-05-03
 */
@Slf4j
public class SubmitFormDialogController {
    @FXML
    private AnchorPane dialogPane;

    @FXML
    private JFXComboBox<Dialect> dialectComboBox;

    @FXML
    private JFXTextField schemaTextField;

    @FXML
    private JFXTextField outputDirTextField;

    @FXML
    public JFXCheckBox deleteInsertCheckBox;

    @FXML
    public JFXCheckBox checkCheckBox;

    @FXML
    public JFXTextArea checkTemplateTextArea;

    @FXML
    private ListView<TransformedExcelVO.TableVO> tableListView;

    @FXML
    private JFXButton cancelButton;

    @FXML
    private JFXButton submitButton;

    private final TransformedExcelVO transExcelVO = TransformedExcelVO.builder().build();

    private final ResourceBundle bundle = ResourceBundleUtil.get();

    @FXML
    public void initialize() {
        tableListView.setCellFactory(param -> new TableListCell());
        bind();
    }

    /**
     * 输出目录按钮事件
     *
     * @param event 事件
     */
    public void onOutputDirButtonAction(ActionEvent event) {
        event.consume();
        final DirectoryChooser chooser = new DirectoryChooser();
        chooser.setTitle(bundle.getString("e2s.submit.chooser.title"));
        Optional.ofNullable(outputDirTextField.getText())
            .filter(StringUtils::isNotBlank)
            .or(CommonConstants.DEFAULT_APP_PATH::describeConstable)
            .map(File::new)
            .ifPresent(chooser::setInitialDirectory);
        File file = chooser.showDialog(StageContext.get());

        if (file != null) {
            outputDirTextField.setText(file.getAbsolutePath());
        }
    }

    /**
     * 展示弹窗
     *
     * @param excelVO excel vo
     */
    public void onShow(ExcelVO excelVO) {
        SingletonFactory.getInstance(ExcelToSqlService.class).transform(excelVO, transExcelVO);
        this.initData();
        // 弹窗
        final JFXDialog dialog = new JFXDialog();
        dialog.setOverlayClose(false);
        dialog.setContent(dialogPane);
        dialog.show(RootPaneContext.get());

        cancelButton.setOnAction(e -> dialog.close());
        submitButton.setOnAction(e -> {
            if (submit()) {
                dialog.close();
            }
        });
    }

    public void onDestroy() {
        // 系统终止时处理
    }

    /**
     * 组件初始化绑定数据
     */
    private void bind() {
        deleteInsertCheckBox.selectedProperty().bindBidirectional(transExcelVO.deleteInsertProperty());
        deleteInsertCheckBox.setSelected(true);
        checkCheckBox.selectedProperty().bindBidirectional(transExcelVO.checkProperty());
        checkCheckBox.setSelected(true);
        checkCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> checkTemplateTextArea.setVisible(newValue));
        schemaTextField.textProperty().bindBidirectional(transExcelVO.defaultSchemaProperty());
        outputDirTextField.textProperty().bindBidirectional(transExcelVO.outputDirProperty());
        // check模板
        checkTemplateTextArea.textProperty().bindBidirectional(transExcelVO.checkTemplateProperty());
        checkTemplateTextArea.setVisible(true);
        // 数据库方言
        dialectComboBox.getItems().addAll(Dialect.values());
        dialectComboBox.setCellFactory(listView -> new DialectListCell());
        dialectComboBox.setButtonCell(new DialectListCell());
        dialectComboBox.valueProperty().bindBidirectional(transExcelVO.dialectProperty());
        // 表格列表
        tableListView.itemsProperty().set(transExcelVO.getTables());
    }

    /**
     * 页面展示初始化数据
     *
     */
    private void initData() {
        // schema
        if (StringUtils.isNotBlank(ConfigurationContext.get().getSchema())
                && StringUtils.isBlank(schemaTextField.getText())) {
            schemaTextField.setText(ConfigurationContext.get().getSchema());
        }
        // dialect
        if (Objects.nonNull(ConfigurationContext.get().getDialect())
                && Objects.isNull(dialectComboBox.getSelectionModel().getSelectedItem())) {
            dialectComboBox.setValue(ConfigurationContext.get().getDialect());
        }
        // check模板
        if (StringUtils.isNotBlank(ConfigurationContext.get().getCheckTemplate())
                && StringUtils.isBlank(checkTemplateTextArea.getText())) {
            checkTemplateTextArea.setText(ConfigurationContext.get().getCheckTemplate());
        } else if (StringUtils.isBlank(checkTemplateTextArea.getText())) {
            checkTemplateTextArea.setText(ExcelToSqlConstants.DEFAULT_CHECK_SQL_TEMPLATE);
        }
    }

    /**
     * 提交
     *
     * @return 是否成功
     */
    private boolean submit() {
        if (Try.of(this::check)
            .failure(e -> {
                String msg = bundle.getString("e2s.submit.message.submit-failed");
                log.error("{}{}", msg, e.getMessage());
                VToast.error(msg + e.getMessage());
            })
            .isFailure()) {
            return false;
        }
        ExcelToSqlService excelToSqlService = SingletonFactory.getInstance(ExcelToSqlService.class);
        return Try.of(() -> excelToSqlService.generateStatement(transExcelVO))
            .failure(e -> {
                String msg = bundle.getString("e2s.submit.message.save-sql-failed");
                 log.error(msg, e);
                 VToast.error(msg + e.getMessage());
             })
            .success(v -> VToast.info(bundle.getString("e2s.submit.message.save-successful")))
            .isSuccess();
    }

    /**
     * 检查
     */
    private void check() {
        // 校验参数
        Assert.notNull(this.dialectComboBox.getValue(), bundle.getString("e2s.submit.message.dialect-is-empty"));
        Assert.notBlank(this.outputDirTextField.getText(), bundle.getString("e2s.submit.message.output-dir-is-empty"));

        for (TransformedExcelVO.TableVO tableVO : this.transExcelVO.getTables()) {
            Assert.check(StringUtils.isNotBlank(tableVO.getSchema())
                    || StringUtils.isNotBlank(transExcelVO.getDefaultSchema()),
                String.format(bundle.getString("e2s.submit.message.both-schema-is-empty"), tableVO.getSheetName()));
            Assert.notBlank(tableVO.getName(),
                String.format(bundle.getString("e2s.submit.message.table-name-is-empty"), tableVO.getSheetName()));
        }
    }
}
